﻿#if !NETCOREAPP
using System;
using System.Collections.Generic;
using System.Reflection;
using CatLib.Container;
using GameFramework;
using GameFramework.Core;
using GameFramework.Network.MessagePack;
using GameFramework.Reference;
using MessagePack.Resolvers;

namespace Server.Proto
{
    public sealed class MsgFactory : IMessageFactory, IInitialize, IDisposable
    {
        private readonly Dictionary<int, Type> m_RouteDict = new Dictionary<int, Type>();

        public void Initialize()
        {
            const string Key = "RouteKey";
            
            var assembly = GetType().Assembly;
            foreach (var type in assembly.GetTypes())
            {
                if (!type.IsClass)
                    continue;

                if (type.IsAbstract)
                    continue;

                if (type.IsSubclassOf(typeof(Message)))
                {
                    var field = type.GetField(Key, BindingFlags.Public | BindingFlags.Static);
                    if (field == null || field.FieldType != typeof(int))
                        continue;
                
                    var route = (int)field.GetValue(null);
                    if (m_RouteDict.TryGetValue(route, out var value))
                    {
                        Log.Error($"Route {route} already exists in {value} and {type}");
                        continue;
                    }

                    m_RouteDict.Add(route, type);
                
                    PolymorphicTypeMapper.Register(type);
                }
                else if (type.IsSubclassOf(typeof(MessageObject)))
                {
                    PolymorphicTypeMapper.Register(type);
                }
            }
            
            PolymorphicResolver.AddInnerResolver(GeneratedResolver.Instance);
            
            PolymorphicTypeMapper.Register(typeof(Message));
            PolymorphicTypeMapper.Register(typeof(RequestMessage));
            PolymorphicTypeMapper.Register(typeof(ResponseMessage));
            PolymorphicTypeMapper.Register(typeof(MessageObject));
            
            PolymorphicResolver.Instance.Init();
        }

        public void Dispose()
        {
            PolymorphicTypeMapper.Clear();
        }

        public Type FindType(int route)
        {
            return m_RouteDict.TryGetValue(route, out var type) ? type : null;
        }
    }
}
#endif